Timewalk measurements in the VeloPix ASIC

1 Introduction

During Run I, LHCb ran at a luminosity (number of collisions per $cm^{2}$ and per second) of $\mathrm{4 \times 10^{32}} \mathrm{cm^{-2}}$ $\mathrm{{s^{-1}}}$ and is expected to increase to $\mathrm{2 \times 10^{33}}$ $\mathrm{m^{-2}s^{-1}}$ The luminosity is restricted by trigger on both hardware and software level and the former VELO has a readout limit of 1 MHz. To run at a higher luminosity, the hardware trigger will be refunded with a full software trigger readout system of 40 MHz.

For this, the current VELO detectors which are based on silicon micro-strip detectors will be replaced by hybrid pixel detectors with 200 $\mathrm{\mu m}$ thick n-on-p silicon sensors bump-bonded to VeloPix ASICs with the 40 MHz readout rate. VeloPix is based on the Timepix3 readout chip and consists of 256 $\times$ 256 pixels of 55 $\mathrm{\mu m}$ pitch.

To exercise the capability of the chip, Nikhef developed a compact readout system called Speedy PIxel Detector Readout (SPIDR). The SPIDR system consists of an Xilinx VC707 FPGA board with various communication interfaces, firmware, CPU subsystem and an API library. The main read-out board connects to both 10 Gb Ethernet and 1 Gb Ethernet devices.

Figure 1: Chip carrier board without ASICs connected to the main SPIDR board.

1.1 VeloPix

Table 1 shows the specifications of VeloPix. As the chip operates with a clock of 40 MHz, hits will be recorded with a precision of 25 ns. One orbit of the LHC is 3564 clock cycles or bunch crossings, and a 9-bit timestamp is used to identify each cycle \cite{Poikela:2042198}. In this note, this timestamp will be referred to as BXID (bunch-crossing identification number).

The front-end of Timepix3 including the super pixel is shown in Figure 2. There is a functionality for test pulse injection which is digitally controlled. The expected detector capacitance C$_{det}$ is approximately 50 fF. With this feature it is possible injects different known amounts of charges into the pixel circuit by adjusting the TpA and TpB voltages applied to the capacitor. Then, the charge value is correlated with the digital readout value. The front-end also has a 4-bit DAC per pixel for threshold tuning.

Readout Type Continuous, trigger-less, binary
Timing resolution/range* 24 ns, 9 bits
Power consumption <1.5 Wcm$^{-2}$
Pixel matrix, pixel size $\mathrm{256 \times 256}$, 55 $\mathrm{\mu m}$ $\times$ 55 $\mathrm{\mu m}$}
Technology Planar silicon, e- collection
Radiation hardness 400 Mrad, SEU tolerant
Sensor type 130 nm CMOS
Maximum data rate 900 Mhits/s/ASIC, 50 khits/s/pixel
Table 1: VeloPix specifications

Figure 2: A schematic of the front-end of VeloPix.

2 Timewalk

As can be seen from Figure 3, the signal takes some time to reach the threshold. The discriminator will detect the signal later than the actual arrival time of the hit on the chip. This delay is called timewalk and depends on the signal amplitude. Timewalk leads to incoherence in the measurement of the z-position of a hit, which expresses as an error in the vertex tracking.

Figure 3: A schematic of the timewalk effect: Pulses of different amplitudes in the preamplifier cross the threshold level at different times. Hence, smaller amplitude signals take longer to detect.

2.1 Method

As mentioned before, in the analog part of the pixel there is also a charge injection circuit (test pulses), with known values, to simulate loads collected by the sensor. By varying the voltages of the test pulse it is possible to simulate the charges generated by particles with different energies going through the sensor.

For this test, a series of charges is applied, controlled by the DAC Vtp_Coarse and Vtp_Fine. These DACs are related to TpA and TpB on Figure 2. The charge value can be calculated from the analog values of Vtp_Coarse and Vtp_Fine which can be read through the chip itself. The injected charge because will be defined by $\mathrm{\Delta VTP = VTP\_coarse - 4 \cdot VTP\_fine}$.

To configure the chip in high-speed readout configuration and apply the test tomeasure timewalk, the following steps were executed:

  • Enable GWT The SPIDR system processes the 20 Gbps scrambled data stream from the VeloPix and distributes it over 1 Gigabit Ethernet link using VELO Gigabit Wireline Transceiver (GWT).

  • Reset and enable PLL and reset GWT DLLs Phase Locked Loop (or phase lock loop) is a control system that generates an output signal whose phase is related to the phase of the input signal. PLL alows the chip to compensate frequency fluctuations in all chips, caused by process parameter and/or temperature variations \cite{Fu_2014}. A delay-locked loop (DLL) is a digital circuit similar to a PLL, but uses a phase (=delay) variable block instead of a frequency block variable.

  • Reset the pixel matrix Reset the pixel before reading data.

  • Do general configurations to link shutter to the test pulse It is necessary to configure the link between the shutter and test pulse. If not linked, the shutter is independent of the test pulse. Otherwise, the shutter only opens when the pulse is enabled.

  • Sweep Pixel Array The active columns and rows are numbered from 0 to 255. Row 0 is the one closest to and row 255 the one furthest away from the periphery. A mask is over the pixels must be applied, activating some pixels and disabling its neighbors, we avoid cross-talk between the pixels. An example of mask is shown in Figure 4.

    After selecting the pixels to sweep the matrix, for each unmasked pixel the test pulse is enabled.

Figure 4: Example of mask application in a 9x9 pixel matrix. The pixels with the bit 1 are enabled, and the pixels with the bit 0 are desabled.
  • Setup the test pulse generation There is one set of TFC commands per BXID, at 40 MHz. TFC will make sure that the system is synchronized or that the usage of command is consistent. In this case, as we are working with TFC, the test pulse is injected into the analog front-end.

    Setting the test pulse voltage the values DAC Vtp_Coarse (fixed at 128) and Vtp_Fine (scanned from 0 to 1024) are writen to its respective registers. However the value $\mathrm{\Delta VTP = VTP\_coarse - 4 \cdot VTP\_fine}$ is the one recorded for analysis.

    It is possible to divide the 25 ns clock into 16 steps, equivalent to 1.5 ns, which is the VeloPix phase. Then, the test pulse is implemented using four parameters: the number of pulses, the test pulse phase, the number of clocks the test pulse is high and the number of clocks the test pulse is low.

2.2 Analysis

Once each pixel has its individual circuit (see Figure 2), the analysis is done pixel by pixel. We divide its 25 ns clock into 16 phases of 1.5 ns. Varying the phase, we can delay the entry of the pulse to see the moment when it changes the Bunch Crossing counter (BXID). Figure 5 shows this behavior for one $\mathrm{\Delta VTP}$ and one pixel only.

Figure 5: Phase vs BXID behavior for pixel in position 0x0 (row x column)

By doing this for multiple charges on the same pixel (see Figure 6), we can confirm that the larger the pulse, the earlier the event is identified.

Figure 6: BXID vs phase for multiple charges, for one pixel. Colors going from yellow (lower $\mathrm{\Delta VTP}$) to pink (higher $\mathrm{\Delta VTP}$)

To quantify timewalk, the approach is to compare the delay calculated as $\mathrm{[BXID+(1.0/16)\times}$ $\mathrm{(15-phase)]}$ with the charge ($\mathrm{\Delta VTP}$). And since BXID and the phase are time measures, we can put them together so we can see what BIXD each voltage has (see Figure 7).

In [3]:
#The code in this notebook is a simpler version of twinterpolation.ipynb, it does not run the full analysis and uses outputs from it.
#The goal is to demonstrate the steps followed at twinterpolation.ipynb notebook.

import ROOT

from ROOT import TCanvas, TPad, TFile, TTree, TPaveLabel, TPaveText, TObject, TLegend
from ROOT import TH1F, TH1D, TF1, TGraph
from ROOT import gROOT, gStyle
from array import array
Welcome to JupyROOT 6.10/04
In [9]:
%jsroot on

# Open input file
# This input file is generated using the method mentioned on section 2.1 but will not be demonstrated on this paper
inputfile = ROOT.TFile.Open('../data/outputfile_negative.root')

# Setup a canvas for plotting. The arguments are a name, an optional title, and the width and height in pixels.
canvas = ROOT.TCanvas("canvas","canvas",800,600)
# Status box configurations
gStyle.SetOptStat('e');
gStyle.SetStatY(0.9);  # Set y-position (fraction of pad size)
gStyle.SetStatX(0.9);  # Set x-position (fraction of pad size)
gStyle.SetStatW(0.2);  # Set width of stat-box (fraction of pad size)
gStyle.SetStatH(0.2);  # Set height of stat-box (fraction of pad size)

#The TFile::Get() method returns a pointer to an object stored in the ROOT file.
htw = inputfile.Get('htwAllperpix_r0_c0')
htw.ls() #list file atrilutes

#Draw histogram
htw.GetYaxis().SetRangeUser(600, 680);
htw.GetZaxis().SetTitle("counts");
htw.Draw('colz')

#Draw Cavas
canvas.Draw()
canvas.SaveAs('../deliver/delay_multiple_vtp.png')
OBJ: TH2F	htwAllperpix_r0_c0	Pixel (0,0) - Negative #Delta VTP : 0 at: 0x4b91d90
Warning in <TCanvas::Constructor>: Deleting canvas with same name: canvas
Info in <TCanvas::Print>: png file ../deliver/images/delay_multiple_vtp.png has been created
Figure 7: Delay for multiples $\mathrm{\Delta VTP}$. Z axis represents the number of pulses counted.

Taking the extremities of the histogram above (Figure 7), we get 3 curves that basically say which event the signal is dropping depending on the height of the pulse.

For this, we project each $\mathrm{\Delta VTP}$ value on the Y axis, leaving us with a "step-like" histograms with the delay for each charge value. We can set a height value, for example 30% of the maximum, and find the point edges (left and right) and midpoint. Figure 8 shows this projections for one of the $\mathrm{\Delta VTP}$ values of the histogram on figure 7. The vertical line represents the height value of 30% of the maximum count rate, where the interceptions point with the "step" are taken.

In [3]:
%jsroot on

canvas2 = ROOT.TCanvas("canvas2","canvas2",800,600)
nbins = htw.GetNbinsX();  
            
# Lower edge histogram
myname =""; myname+=htw.GetName(); myname+="_lowEdge"; 
hlowEdge = TH1F(myname, 'low',
                    htw.GetNbinsX(),
                    htw.GetXaxis().GetBinLowEdge(1),
                    htw.GetXaxis().GetBinLowEdge(nbins+1));

# Middle point historram
myname =""; myname+=htw.GetName(); myname+="_averageEdge";
haverageEdge = TH1F(myname, 'avg', 
                    htw.GetNbinsX(), 
                    htw.GetXaxis().GetBinLowEdge(1), 
                    htw.GetXaxis().GetBinLowEdge(nbins+1));

# Upper edge histogram
myname =""; myname+=htw.GetName(); myname+="_highEdge";
hhighEdge = TH1F(myname, 'up', 
                    htw.GetNbinsX(), 
                    htw.GetXaxis().GetBinLowEdge(1), 
                    htw.GetXaxis().GetBinLowEdge(nbins+1));
            
idelta = 1
for idelta in range(0,513):  #dVTP voltages
    myname2 =""; myname2 += htw.GetName(); myname2 +="_";myname2 +=str(idelta);

    tempproj = htw.ProjectionY(myname2, idelta, idelta);
    
    cpup = 0
    cpdown = 0;
    
    # Histogram only for demonstration of the analysis
    # A linear function is fitted just to represent the height at 30% of maximum, does not have any relevancy on the final analysis
    # The analysis is done at twinterpolation.ipynb notebook
    if(idelta==113):
        maxpoint   = tempproj.GetMaximum();
        edgepoint  = maxpoint*0.30;
        func = TF1('func', '[0]', 0, 10);
        func.SetParameter(0, edgepoint)
        func.SetParLimits(0, edgepoint, edgepoint)
        fit = tempproj.Fit('func', 'S');
        func.SetTitle('30 #% height');
        tempproj.GetYaxis().SetTitle('counts');
        tempproj.SetTitle('Pixel(0,0) at |#Delta VTP| = 113');
        tempproj.Draw();
        fit.Draw();        
        leg = TLegend(0.9,0.4,0.7,0.5);
        #leg->SetHeader("The Legend Title");
        leg.AddEntry(func,"30% height","l");
        leg.Draw();

        canvas2.Draw();
 FCN=3734.75 FROM FIX         STATUS=RESET           0 CALLS           0 TOTAL
                     EDM= unknown      STRATEGY= 1      NO ERROR MATRIX       
  EXT PARAMETER               CURRENT GUESS       STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  p0           6.60000e+01     fixed    
Figure 8: "step-like" histogram representing the projection of the previous histogram at the $\mathrm{\Delta VTP}$ value of 113. The points of the histograms that crosses the illustrative red line are the edges of the first histograms from this specific charge value. $\mathrm{\Delta VTP}$

The first point that the histogram intercepts the line is being called "Lower edge", the second interception point is called "Upper edge". The middle point, taking the middle distance between them, is called "Average point".

Taking the edge points for all $\mathrm{\Delta VTP}$ values, we get 3 curves that basically say which event the signal is dropping depending on the height of the pulse (see Figure 9).

In [4]:
%jsroot on

canvas3 = ROOT.TCanvas("canvas3","canvas3",800,600);

# Open demonstration file. The analysis was made using twinterpolation.ipynb
# This file has only the results for pixel 0x0 to be a smaller size. 
inputfile = ROOT.TFile.Open('../results/htwInterpPix_demonstration.root');

# Get histograms from input file
htw_original = inputfile.Get('htwAllperpix_r0_c0');
htw_low      = inputfile.Get('htwAllperpix_r0_c0_lowEdge');
htw_up       = inputfile.Get('htwAllperpix_r0_c0_highEdge');
htw_mid      = inputfile.Get('htwAllperpix_r0_c0_averageEdge');

# Status box configurations
gStyle.SetOptStat('e');
gStyle.SetStatY(0.9);  # Set y-position (fraction of pad size)
gStyle.SetStatX(0.9);  # Set x-position (fraction of pad size)
gStyle.SetStatW(0.2);  # Set width of stat-box (fraction of pad size)
gStyle.SetStatH(0.2);  # Set height of stat-box (fraction of pad size)
htw_up.SetMarkerColor(4);

#Draw histogram
htw_original.GetYaxis().SetRangeUser(600, 680);
htw_original.Draw('colz');
htw_low.Draw('psame');
htw_up.Draw('psame');
htw_mid.Draw('psame');

legend = TLegend(0.1,0.77,0.48,0.9);
legend.AddEntry(htw_low,"Upper edge points", "p");
legend.AddEntry(htw_up,"Lower edge points", "p");
legend.AddEntry(htw_mid,"Average points", "p");
legend.Draw();

canvas3.Draw();
canvas3.SaveAs('../deliver/delay_multiple_vtp_with_points.png')
Info in <TCanvas::Print>: png file ../deliver/images/delay_multiple_vtp_with_points.png has been created
Figure 9: Edge points for all $\mathrm{\Delta VTP}$ values.

As all 3 curves behave the same way, we can chose the lower edge and fit an appropriate function, which in the case is an hyperbolic.

$\frac{p0}{(|\Delta VTP| - p1)^{p2}} + p3$
In [5]:
%jsroot on

canvas4 = ROOT.TCanvas("canvas3","canvas3",800,600);

# Open demonstration file. The analysis was made using twinterpolation.ipynb
# This file has only the results for pixel 0x0 to be a smaller size. 
inputfile = ROOT.TFile.Open('../results/htwInterpPix_demonstration.root');

# Get histogram from input file
htw_low      = inputfile.Get('htwAllperpix_r0_c0_lowEdge');

# Status box configurations
gStyle.SetOptStat(0);
gStyle.SetOptFit(101111);
gStyle.SetStatY(0.9);  # Set y-position (fraction of pad size)
gStyle.SetStatX(0.9);  # Set x-position (fraction of pad size)
gStyle.SetStatW(0.19);  # Set width of stat-box (fraction of pad size)
gStyle.SetStatH(0.15);  # Set height of stat-box (fraction of pad size)
htw_up.SetMarkerColor(4);

#Draw histogram
htw_low.GetYaxis().SetRangeUser(600, 680);
htw_low.Draw('psame');


# Fit configurations
print(" --------------------------- LOWER CURVE: Fitting --------------------------------- ")

htw_low.SetTitle("Plot for pixel 0x0 - Lower Edge; |#Delta VTP|; BXID+(1.0/16)*(15-phase)  [ns]");
funcname = "fit";
func = ""; func+=funcname; func+=str(0); func+="_c"; func+=str(0);
lowerfuncname = func+"_lowcurve";

# Initial parameters
initx = htw_low.GetBinCenter(htw_low.GetMaximumBin()); # Get maximun bin for the x range
lastx  = htw_low.FindLastBinAbove(0,1); # Get last bin with content > 0 for the x range
maxx   = htw_low.GetBinCenter(htw_low.GetMaximumBin()); # Get maximun bin to set fit parameters
maxy   = htw_low.GetBinContent(htw_low.GetMaximumBin()); # Return content of bin number bin to set fi parameters

print("X axis range = ["+ str(initx) + ", " + str(lastx) + "]");
print("Maximun bin = " + str(maxx));
print("Content of maximun bin = " + str(maxy));

par3_hint_bin = htw_low.FindBin(lastx);
par3_hint     = htw_low.GetBinContent(par3_hint_bin);

# Define fuction
lowerfunc = TF1(lowerfuncname,"([0]/(x-[1])**[2]) + [3]" , 0, 510);

# Set fit parameter values
lowerfunc.SetParameters(100, maxx-1, 0.9, par3_hint);
lowerfunc.SetParLimits(0, 0, 4000);
lowerfunc.SetParLimits(1, -20, 20);
lowerfunc.SetParLimits(2, 0.1, 4);
lowerfunc.SetLineWidth(2);
lowerfunc.SetLineStyle(1);
lowerfunc.SetLineColor(4);
lowerfunc.SetMaximum(maxy);
lowerfunc.SetRange(initx-1, lastx);

# Fit function
htw_low.Fit(lowerfuncname, "MR0W", "", initx+1, lastx);
htw_low.SetMarkerSize(0.6);
htw_low.Draw("p");
lowerfunc.Draw("same");

canvas4.Draw();
canvas4.SaveAs('../deliver/low_edge_fit_0x0.png')
 --------------------------- LOWER CURVE: Fitting --------------------------------- 
X axis range = [18.0, 511]
Maximun bin = 18.0
Content of maximun bin = 662.49609375
 FCN=508.949 FROM HESSE     STATUS=OK             23 CALLS         822 TOTAL
                     EDM=1.3637e-06    STRATEGY= 1      ERROR MATRIX ACCURATE 
  EXT PARAMETER                                   STEP         FIRST   
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE 
   1  p0           1.41014e+02   3.08400e+01   6.21332e-06   2.31883e-01
   2  p1           1.53289e+01   6.54543e-01   2.03233e-05   1.35355e-01
   3  p2           8.77258e-01   7.13238e-02   7.97614e-06  -6.99361e-02
   4  p3           6.08853e+02   2.51993e-01   1.81888e-04   2.40032e-03
Warning in <TCanvas::Constructor>: Deleting canvas with same name: canvas3
Info in <TCanvas::Print>: png file ../deliver/images/low_edge_fit_0x0.png has been created
Figure 10: Fit for pixel 0x0.

Doing this for all pixels in the matrix we see the parameters behavior.

Now, we can use this result to calculate the minimum charge necessary to detect a collision in the right event/BXID. First, taking time related to the highest charge injected, and since the function has a horizontal asymptote (Figure \ref{fig:fit}) this also corresponds to the time of a very large charge (see Figure \ref{fig:tmin}. With the time value of an infinite charge, we can look for the charge that makes the difference between the time of a very large charge and p3 less than 25 ns, which will tell us the minimal in-time charge (see Figure \ref{fig:twalk}).

From the right histogram in Figure \ref{fig:twalk}, we can find a global timewalk of about 18 ns. This means that a pulse detection difference greater than this value for this pixel causes the pulse to be counted as another event.

3 Conclusion

In total, VELO consists of 52 modules positioned in vacuum along the LHC beampipe, surrounding the interaction point, summing 624 VeloPix ASICs. This paper proposes a method to quantify the Timewalk effect on the VeloPix ASIC.

What Figure 15 shows is the minimum charge required to have a particle hit associated with the same event of higher charges. At the VELO, if a particle from a certain collision with a charge is less than the minimum calculated for that chip, this hit will not be identified that same collision, but the next one.

This analysis can be used as a basis for further investigations on the subject. And as this ASIC is derived from the Medipix family, this study can be adapted to other chips as well.

References

[1] Y Fu, C Brezina, K Desch, T Poikela, X Llopart, M Campbell, D Massimiliano, V Gro-mov, R Kluit, M van Beauzekom, F Zappon, and V Zivkovic. The charge pump PLLclock generator designed for the 1.56 ns bin size time-to-digital converter pixel arrayof the timepix3 readout ASIC.Journal of Instrumentation, 9(01):C01052–C01052, jan2014.

[2] Tuomas Sakari Poikela. Readout Architecture for Hybrid Pixel Readout Chips, Apr 2015.Presented 15 Jun 2015.

[3] J Visser, M van Beuzekom, Henk Boterenbrood, B van der Heijden, J I Mu ̃noz, S Kulis,B Munneke, and F Schreuder. SPIDR: a read-out system for Medipix3 amp; Timepix3.JINST, 10(12):C12028, 2015.13

In [ ]: